import os
import sys
import base64
import mimetypes
import requests
import json
import uuid
from pathlib import Path
from dashscope import MultiModalConversation
import dashscope
from dotenv import load_dotenv

# 加载.env文件中的环境变量
load_dotenv()

# 设置API密钥和基础URL
api_key = os.getenv("DASHSCOPE_API_KEY")
dashscope.base_http_api_url = 'https://dashscope.aliyuncs.com/api/v1'

# 检查API密钥是否存在
if not api_key:
    raise ValueError("未找到DASHSCOPE_API_KEY环境变量，请检查.env文件配置")


def encode_file(file_path):
    """
    将图片文件编码为Base64格式
    格式为 data:{mime_type};base64,{base64_data}
    """
    mime_type, _ = mimetypes.guess_type(file_path)
    if not mime_type or not mime_type.startswith("image/"):
        raise ValueError("不支持或无法识别的图像格式")

    try:
        with open(file_path, "rb") as image_file:
            encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
        return f"data:{mime_type};base64,{encoded_string}"
    except IOError as e:
        raise IOError(f"读取文件时出错: {file_path}, 错误: {str(e)}")


def is_oss_url(url):
    """
    检查URL是否为OSS URL
    
    Args:
        url (str): 待检查的URL
        
    Returns:
        bool: 如果是OSS URL返回True，否则返回False
    """
    # 检查url是否为字符串类型
    if not isinstance(url, str):
        return False
    return url.startswith("oss://")


def edit_image(image_paths, prompt, negative_prompt=" "):
    """
    编辑图片，根据提示词生成新的图片
    
    Args:
        image_paths (str or list): 输入图片路径或OSS URL，可以是单个路径或路径列表
        prompt (str): 图片编辑提示词
        negative_prompt (str): 负面提示词
        
    Returns:
        tuple: (成功状态, 结果信息)
               成功时返回 (True, 图片URL)
               失败时返回 (False, 错误信息)
    """
    try:
        # 确保image_paths是列表格式
        if isinstance(image_paths, str):
            image_paths = [image_paths]
        
        # 构建消息内容
        content = []
        
        # 添加所有图片
        for image_path in image_paths:
            if is_oss_url(image_path) or (isinstance(image_path, str) and image_path.startswith("data:")):
                # 如果是OSS URL或Base64数据，直接使用
                content.append({"image": image_path})
            else:
                # 如果是本地文件路径，检查文件是否存在
                if not os.path.exists(image_path):
                    raise IOError(f"文件不存在: {image_path}")
                # 获取图像的 Base64 编码
                image_data = encode_file(image_path)
                content.append({"image": image_data})
        
        # 添加文本提示
        content.append({"text": prompt})

        messages = [
            {
                "role": "user",
                "content": content
            }
        ]

        # 模型仅支持单轮对话，复用了多轮对话的接口
        response = MultiModalConversation.call(
            api_key=api_key,
            model="qwen-image-edit",
            messages=messages,
            stream=False,
            watermark=False,
            negative_prompt=negative_prompt
        )

        if response.status_code == 200:
            # 返回生成的图像URL
            image_url = response.output.choices[0].message.content[0]['image']
            return True, image_url
        else:
            error_info = {
                "status_code": response.status_code,
                "code": response.code,
                "message": response.message
            }
            return False, error_info
            
    except Exception as e:
        return False, str(e)


def download_image(image_url, save_path):
    """
    下载生成的图片到本地
    
    Args:
        image_url (str): 图片URL
        save_path (str): 保存路径
        
    Returns:
        bool: 下载是否成功
    """
    try:
        response = requests.get(image_url, stream=True, timeout=300)  # 设置超时
        response.raise_for_status()  # 如果HTTP状态码不是200，则引发异常
        with open(save_path, 'wb') as f:
            for chunk in response.iter_content(chunk_size=8192):
                f.write(chunk)
        return True
    except requests.exceptions.RequestException as e:
        print(f"图像下载失败: {e}")
        return False


def process_image_edit(image_paths, prompt, negative_prompt=" ", output_path=None):
    """
    处理完整的图片编辑流程：编辑图片并下载结果
    
    Args:
        image_paths (str or list): 输入图片路径，可以是单个路径或路径列表
        prompt (str): 图片编辑提示词
        negative_prompt (str): 负面提示词
        output_path (str): 输出图片路径，如果为None则自动生成
        
    Returns:
        tuple: (成功状态, 结果信息)
    """
    # 如果没有指定输出路径，则自动生成（仅适用于单张图片）
    if output_path is None:
        if isinstance(image_paths, list):
            # 对于多张图片，使用第一张图片的路径生成输出路径
            first_path = image_paths[0]
            path_obj = Path(first_path)
            output_path = path_obj.parent / f"{path_obj.stem}_edited_{uuid.uuid4().hex[:8]}{path_obj.suffix}"
        else:
            path_obj = Path(image_paths)
            output_path = path_obj.parent / f"{path_obj.stem}_edited_{uuid.uuid4().hex[:8]}{path_obj.suffix}"
    
    # 编辑图片
    success, result = edit_image(image_paths, prompt, negative_prompt)
    
    if not success:
        return False, f"图片编辑失败: {result}"
    
    # 下载生成的图片
    image_url = result
    download_success = download_image(image_url, output_path)
    
    if not download_success:
        return False, "图片下载失败"
    
    return True, str(output_path)